package club.kingyin.component;

import club.kingyin.annotation.Component;
import club.kingyin.context.AbstractApplicationContext;
import club.kingyin.core.Scope;

import java.io.File;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;

/**
 * @author : kingyins
 * @version : 1.0
 * @program : my-spring
 * @description : 自动扫描器，自动注册BD到容器
 * @create : 2021年07月19日 17:02
 **/
public class BeanDefinitionClassPathScanner {

    private String path;

    public BeanDefinitionClassPathScanner(String path) {
        this.path = path;
    }

    public int scan(AbstractApplicationContext register, String ... paths) {
        int count = 0;
        for (String path : paths) {
            Set<DefaultBeanDefinition> beanDefinitions = doScan(path);
            beanDefinitions.forEach(register::registerBeanDefinition);
            count += beanDefinitions.size();
        }
        return count;
    }

    // 扫描逻辑
    public Set<DefaultBeanDefinition> doScan(String path) {
        URL resource = this.getClass().getResource("/");
        path = path.replace(".", "/");
        path = resource.getPath() + path;
        File file = new File(path);
        Set<DefaultBeanDefinition> beanDefinitions = new HashSet<>();
        try {
            getClassFile(file, beanDefinitions);
            return beanDefinitions;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    public boolean isComponentBean(Class<?> classType) {
        if (classType.isAnnotationPresent(Component.class)) {
            return !Modifier.isAbstract(classType.getModifiers()) &&
                    !Modifier.isInterface(Modifier.classModifiers());
        }
        return false;
    }

    private void getClassFile(File dir, Set<DefaultBeanDefinition> bds) throws ClassNotFoundException {
        if (dir.isDirectory()) {
            // 获得所有文件
            File[] files = dir.listFiles();
            for (File file : files) {
                // 是目录
                if (file.isDirectory()) {
                    // 路径动态变化
                    path += "." + file.getName();
                    getClassFile(file, bds);
                    path = path.substring(0, path.lastIndexOf("."));
                } else {
                    // 是class文件
                    if (file.getName().endsWith(".class")) {

                        String className = path +"."+ file.getName().replace(".class", "");
                        Class<?> beanType = getClass().getClassLoader().loadClass(className);

                        // 是bean
                        if (isComponentBean(beanType)) {
                            DefaultBeanDefinition beanDefinition = new DefaultBeanDefinition();
                            beanDefinition.setBeanClassName(className);
                            // 获得Scope
                            Scope scope = getScope(beanType);
                            beanDefinition.setScope(scope);
                            // 加入缓存
                            bds.add(beanDefinition);
                            System.out.println("创建 BeanDefinition : "+className);
                        }
                    }
                }
            }
        } else {
            throw new RuntimeException("扫描路径不是目录 '"+path+"'");
        }
    }

    private Scope getScope(Class<?> beanType) {
        Component declaredAnnotation = beanType.getDeclaredAnnotation(Component.class);
        return declaredAnnotation.scope();
    }

}
